/*
 * Copyrignt (c) xuzeshui.com. All Rights Reserved.
 * Author: Zeshui Xu<i@xuzeshui.com>
 * Created Time: 2015-12-15 11:28:33
 * Last Modified: 2016-05-20 10:56:19
 * File Name: invitecode/invitecode.go
 * Description:
 */
package invitecode

import (
	"fmt"
	"strconv"
	"time"

	"passport/account"
	"passport/avatar"
	"passport/models"
	"passport/user"

	log "github.com/cihub/seelog"
	"github.com/garyburd/redigo/redis"
)

var (
	inviteCodeService *InviteCodeService
)

/*
	邀请码好友查询
*/
type InviteCodeFriendsQueryReq struct {
	Userid    string //自己的userid
	PageIndex int32  //第几页数据
}

/*
	邀请码好友查询响应
*/
type InviteCodeFriendsQueryResp struct {
	FriendsCnt int32                  `json:"friends_cnt"` //总共好友数目
	PageIndex  int32                  `json:"page"`        //当前页数
	Friends    []*InviteRegFriendInfo `json:"friends"`     //邀请注册的好友信息
}

type InviteRegFriendInfo struct {
	Userid   string `json:"uid"`
	NickName string `json:"nick_name"`
	Avatar   string `json:"avatar"`
	RegTime  string `json:"reg_time"`
}

/*
	邀请码服务接口
*/
type InviteCodeService struct {
}

/*
	获取等待分配的邀请码队列名称key
*/
func (p *InviteCodeService) getDispInviteCodeQueueKey() string {
	return "ic:dispcode"
}

/*
	邀请码好友列表key
*/
func (p *InviteCodeService) getFriendsKey(userid string) string {
	return fmt.Sprintf("icu:%s", userid)
}

/*
	特殊邀请码
*/
func (p *InviteCodeService) IsSpecialInviteCode(inviteCode string) bool {
	return p.isCorrectOfficeInviteCode(inviteCode) || inviteCode == "CWDS8888"
}

/*
	判断是否办事处邀请码
	1101~1399 号段分配给网络各办,后面允许最多加4位用户办事处自己分配
*/
func (p *InviteCodeService) isCorrectOfficeInviteCode(inviteCode string) bool {
	if len(inviteCode) < 4 || len(inviteCode) > 8 {
		return false
	}
	officeCode := inviteCode[0:4]
	if officeId, err := strconv.Atoi(officeCode); err == nil && officeId >= 1101 && officeId <= 1399 {
		return true
	}
	return false
}

/*
	根据注册邀请码获取对应的userid,如果返回空表示错误
*/
func (p *InviteCodeService) GetUseridByInviteCode(inviteCode string) string {
	if "" == inviteCode {
		return ""
	}

	ai, err := account.GetAccountService().GetAllAccountInfo(account.Account_TYPE_INVITE_CODE, inviteCode)
	if err != nil {
		return ""
	}

	if ai == nil { //不存在
		return ""
	}
	return ai.Userid
}

/*
	查询邀请了多少好友
*/
func (p *InviteCodeService) QueryInviteCodeRegNumber(userid string) int32 {
	rkey := p.getFriendsKey(userid)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	if reply, err := redis.Int(conn.Do("llen", rkey)); err == nil {
		return int32(reply)
	}
	return 0
}

/*
	查询自己的邀请码有哪些好友
*/
func (p *InviteCodeService) QueryInviteCodeRegFriends(req *InviteCodeFriendsQueryReq, resp *InviteCodeFriendsQueryResp) error {
	rkey := p.getFriendsKey(req.Userid)
	startIdx := req.PageIndex * 20
	endIdx := startIdx + 19
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	conn.Send("llen", rkey)
	conn.Send("lrange", rkey, startIdx, endIdx)
	conn.Flush()
	if reply, err := redis.Int(conn.Receive()); err == nil {
		resp.FriendsCnt = int32(reply)
		resp.PageIndex = req.PageIndex
		if reply, err := redis.Strings(conn.Receive()); err == nil {
			resp.Friends = make([]*InviteRegFriendInfo, 0, len(reply))
			for _, userid := range reply {
				uinfo, _ := user.GetUserService().GetAllUserInfo(userid)
				if uinfo != nil {
					finfo := &InviteRegFriendInfo{}
					finfo.Userid = userid
					finfo.NickName = uinfo.NickName
					if len(uinfo.Avatar) == 32 {
						finfo.Avatar, _ = avatar.GetAvatarURL(uinfo.Avatar)
					} else {
						finfo.Avatar = uinfo.Avatar
					}
					finfo.RegTime = uinfo.InsertTime
					resp.Friends = append(resp.Friends, finfo)
				}
			}
		} else {
			log.Errorf("QueryInviteCodeRegFriends error: %s", err.Error())
			return err
		}
	} else {
		log.Errorf("QueryInviteCodeRegFriends error: %s", err.Error())
		return err
	}
	return nil
}

/*
	获取一个未分配的新验证码
*/
func (p *InviteCodeService) ObtainNewInviteCode() string {
	ickey := p.getDispInviteCodeQueueKey()
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	if reply, err := redis.String(conn.Do("lpop", ickey)); err == nil {
		return reply
	} else if redis.ErrNil == err {
		return ""
	} else {
		log.Errorf("cmd: lpop %s, msg: %s", ickey, err.Error())
	}
	return ""
}

/*
	归还邀请码
*/
func (p *InviteCodeService) GivebackInviteCode(inviteCode string) error {
	ickey := p.getDispInviteCodeQueueKey()
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	_, err := conn.Do("rpush", ickey, inviteCode)
	return err
}

/*
	创建一个邀请码账号,但禁止登录
*/
func (p *InviteCodeService) CreateICAccount(userid, inviteCode string) {
	aichanger := account.NewAccountInfoChanger(inviteCode, account.Account_TYPE_INVITE_CODE)
	aichanger.SetAccount(inviteCode)
	aichanger.SetAccountType(account.Account_TYPE_INVITE_CODE)
	aichanger.SetUserid(userid)
	aichanger.SetThirdAccount(account.AI_SELF_ACCOUNT)
	aichanger.SetBindStatus(account.AI_BIND_STATUS)
	aichanger.SetActive(account.AI_ACTIVE_NOLOGIN)
	aichanger.SetInsertTime(time.Now().Format("2006-01-02 15:04:05"))
	aichanger.Save()
}

/*
	删除邀请码账号
*/
func (p *InviteCodeService) DeleteICAccount(inviteCode string) {
	aichanger := account.NewAccountInfoChanger(inviteCode, account.Account_TYPE_INVITE_CODE)
	aichanger.Delete()
}

/*
	fuid是通过userid的邀请码注册成功的
*/
func (p *InviteCodeService) RegSuccFromInviteCode(userid, fuid string) {
	rkey := p.getFriendsKey(userid)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	conn.Do("lpush", rkey, fuid)
}

/*
	删除所有邀请码注册纪录
*/
func (p *InviteCodeService) ClearInviteCodeRegRecord(userid string) {
	rkey := p.getFriendsKey(userid)
	conn := models.GetPassportModel().Get()
	defer conn.Close()
	conn.Do("del", rkey)
}

func GetInviteCodeService() *InviteCodeService {
	return inviteCodeService
}

func init() {
	inviteCodeService = &InviteCodeService{}
}
